package ar.com.osdepym.agregacionafip.servicios;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.mail.MessagingException;
import javax.mail.internet.AddressException;

import ar.com.osdepym.agregacionafip.activities.context.Results;
import ar.com.osdepym.agregacionafip.adapters.Contenedor;
import ar.com.osdepym.agregacionafip.configuracion.ConfiguracionAplicacion;
import ar.com.osdepym.agregacionafip.exceptions.NoDestinatariosException;
import ar.com.osdepym.agregacionafip.exceptions.ResultadoYaExisteExeption;
import ar.com.osdepym.agregacionafip.modelfile.Archivo;
import ar.com.osdepym.agregacionafip.modelfile.FactoryArchivo;
import ar.com.osdepym.agregacionafip.modelfile.Resultado;

public class ProcesadorArchivos {

	private ServicioArchivos sa;

	public ProcesadorArchivos() {
		sa = new ServicioArchivos();
	}

	public Results procesarArchivos(List<Contenedor> contenedor,
			ConfiguracionAplicacion conf) {

		Results resultados = new Results();
		Resultado resultado = null;
		this.moverArchivos(contenedor, conf.getDirectorioEntrada(),
				conf.getDirectorioEnProceso());

		String cabecera = null;
		BufferedReader fin = null;
		OutputStreamWriter fout = null;
		for (Contenedor contenedor2 : contenedor) {

			File file = sa.getFile(conf.getDirectorioEnProceso(),
					contenedor2.getNombre());

			try {
				File archivoSalida = this.crearArchivoSalida(conf,
						contenedor2.getNombre());
				fin = new BufferedReader(new InputStreamReader(
						new FileInputStream(file)));
				fout = new OutputStreamWriter(new FileOutputStream(
						archivoSalida));

				if (fin.ready()) {
					cabecera = fin.readLine();
				}

				@SuppressWarnings("rawtypes")
				Archivo archivo = FactoryArchivo.getArchivoByHeader(cabecera);

				resultado = archivo.procesar(fin, conf, fout);
				resultado.setContenedor(contenedor2);
				resultado.setArchivoEntrada(contenedor2.getNombre());
				resultado.getContenedor().setNombre(archivoSalida.getName());
				resultado.setArchivoSalida(archivoSalida.getName());

				fin.close();
				fout.close();
				
				if (resultado.getEstado() == Resultado.PROCESADO_OK
						|| resultado.getEstado() == Resultado.DIFERENCIA_TOTALES) {

					sa.borrarArchivo(file);

					if (resultado.getEstado() == Resultado.PROCESADO_OK) {
						if (conf.getDestinatariosExito().size() > 0)
							this.enviarMailCorrecto(conf, resultado);
						if (conf.getDestinatariosArchivo().size() > 0
								&& conf.isComprirmir())
							this.enviarMailCorrectoAdjunto(conf, resultado,
									archivoSalida);
					} else {
						if (conf.getDestinatariosFalla().size() > 0) {
							this.enviarMailDiferenciaTotales(conf, resultado);
							this.enviarMailDirefenciaTotalesAdjunto(conf,
									resultado, archivoSalida);
						}
					}
				}

			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoDestinatariosException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			try {
				resultados.put(resultado);
			} catch (ResultadoYaExisteExeption e) {

				e.printStackTrace();
			} finally {
				try {
					if (fin != null)

						fin.close();

					if (fout != null)

						fout.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

		this.borrarTemp();
		return resultados;
	}

	private void borrarTemp() {
		File file = sa.crearDirectorio("temp");
		sa.deleteWithChildren(file);
	}

	private File crearArchivoSalida(ConfiguracionAplicacion conf, String nombre) {

		File archivoSalida = sa.crearArchivo(conf.getDirectorioProcesados(),
				this.crearNombreArchivoSalida(nombre, conf));

		return archivoSalida;
	}

	private void moverArchivos(List<Contenedor> contenedor, String origen,
			String destino) {

		for (Contenedor archivo : contenedor) {
			File file = sa.getFile(origen, archivo.getNombre());
			sa.copiarArchivo(file, destino);
		}
	}

	public void moverArchivoErroneo(String archivo, ConfiguracionAplicacion conf) {

		File file = sa.getFile(conf.getDirectorioEntrada(), archivo);

		sa.copiarArchivo(file, conf.getDirectorioProcesados());

		file = sa.getFile(conf.getDirectorioProcesados(), archivo);

		sa.renombrarArchivo(file, this.crearNombreArchivoSalida(archivo, conf));

	}

	public String crearNombreArchivoSalida(String nombreArchivoEntrada,
			ConfiguracionAplicacion conf) {

		SimpleDateFormat formatoDelTexto = new SimpleDateFormat(
				"yyyyMMddhhmmss");
		String campoString = formatoDelTexto.format(new Date());
		String nombreArchivoSalida = nombreArchivoEntrada + campoString
				+ conf.getAnexoArchivoSalida();
		
		if(nombreArchivoSalida.contains(".txt")){
			int indice = nombreArchivoEntrada.indexOf(".");
			nombreArchivoSalida = nombreArchivoEntrada.substring(0,indice) + campoString + nombreArchivoEntrada.substring(indice);
		}
		else nombreArchivoSalida = nombreArchivoEntrada.concat(campoString);


		return nombreArchivoSalida;
	}

	private void enviarMailCorrecto(ConfiguracionAplicacion conf,
			Resultado resultado) throws NoDestinatariosException {
		MailSender servicioMail = new MailSender(conf);
		servicioMail
				.setAsunto("Resultado ejecucion exitosa para - Agregacion de AFIP.  Archivo: "
						+ resultado.getArchivoEntrada());
		List<Contenedor> contenedor = conf.getDestinatariosExito();
		if (!contenedor.isEmpty()) {
			try {
				servicioMail.setEnviadoPor(conf.getCuentaEnvio());
				for (Contenedor contenedor2 : contenedor) {
					servicioMail.addDestinatario(contenedor2.getNombre());
				}
			} catch (AddressException e) {
				e.printStackTrace();
			}

			servicioMail.setearTexto(resultado);

			try {
				servicioMail.send();
			} catch (MessagingException e) {
				e.printStackTrace();
			}
		} else {
			throw new NoDestinatariosException();
		}
	}

	private void enviarMailCorrectoAdjunto(ConfiguracionAplicacion conf,
			Resultado resultado, File archivoSalida)
			throws NoDestinatariosException {
		MailSender servicioMail = new MailSender(conf);
		servicioMail
				.setAsunto("Resultado ejecucion exitosa adjunto para - Agregacion de AFIP.  Archivo: "
						+ resultado.getArchivoEntrada());
		List<Contenedor> contenedor = conf.getDestinatariosArchivo();
		if (!contenedor.isEmpty()) {
			try {
				servicioMail.setEnviadoPor(conf.getCuentaEnvio());
				for (Contenedor contenedor2 : contenedor) {
					servicioMail.addDestinatario(contenedor2.getNombre());
				}
			} catch (AddressException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			servicioMail.setearTexto(resultado);
			if (conf.isComprirmir()) {
				String temporal = "temp";
				File directorioTemporal = sa.crearDirectorio(temporal);
				this.comprimirArchivo(archivoSalida,
						directorioTemporal.getAbsolutePath());
				servicioMail
						.addAdjunto(
								sa.obtenerNombreArchivoZipeado(archivoSalida),
								directorioTemporal.getAbsolutePath()
										+ "/"
										+ sa.obtenerNombreArchivoZipeado(archivoSalida));
			} else {
				servicioMail.addAdjunto(archivoSalida.getName(),
						archivoSalida.getAbsolutePath());
			}

			try {
				servicioMail.send();
			} catch (MessagingException e) {
				e.printStackTrace();
			}
		} else {
			throw new NoDestinatariosException();
		}
	}

	private void enviarMailDirefenciaTotalesAdjunto(
			ConfiguracionAplicacion conf, Resultado resultado,
			File archivoSalida) throws NoDestinatariosException {
		MailSender servicioMail = new MailSender(conf);
		servicioMail
				.setAsunto("Resultado ejecucion con diferencia en controles - Agregacion de AFIP.  Archivo: "
						+ resultado.getArchivoEntrada());
		List<Contenedor> contenedor = conf.getDestinatariosArchivo();
		if (!contenedor.isEmpty()) {
			try {
				servicioMail.setEnviadoPor(conf.getCuentaEnvio());
				for (Contenedor contenedor2 : contenedor) {
					servicioMail.addDestinatario(contenedor2.getNombre());
				}
			} catch (AddressException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			servicioMail.setearTexto(resultado);
			if (conf.isComprirmir()) {
				String temporal = "temp";
				File directorioTemporal = sa.crearDirectorio(temporal);
				this.comprimirArchivo(archivoSalida,
						directorioTemporal.getAbsolutePath());
				servicioMail
						.addAdjunto(
								sa.obtenerNombreArchivoZipeado(archivoSalida),
								directorioTemporal.getAbsolutePath()
										+ "/"
										+ sa.obtenerNombreArchivoZipeado(archivoSalida));
			} else {
				servicioMail.addAdjunto(archivoSalida.getName(),
						archivoSalida.getAbsolutePath());
			}

			try {
				servicioMail.send();
			} catch (MessagingException e) {
				e.printStackTrace();
			}
		} else {
			throw new NoDestinatariosException();
		}
	}

	public void enviarMailFormatoIncorrectoAdjunto(
			ConfiguracionAplicacion conf, Resultado resultado)
			throws NoDestinatariosException {
		MailSender servicioMail = new MailSender(conf);
		servicioMail
				.setAsunto("Resultado ejecucion con diferencia en controles - Agregacion de AFIP.  Archivo: "
						+ resultado.getArchivoEntrada());
		List<Contenedor> contenedor = conf.getDestinatariosArchivo();
		ServicioArchivos sa = new ServicioArchivos();
		File archivoSalida = sa.getFile(conf.getDirectorioProcesados(),
				resultado.getArchivoSalida());

		if (!contenedor.isEmpty()) {
			try {
				servicioMail.setEnviadoPor(conf.getCuentaEnvio());
				for (Contenedor contenedor2 : contenedor) {
					servicioMail.addDestinatario(contenedor2.getNombre());
				}
			} catch (AddressException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			servicioMail.setearTexto(resultado);
			if (conf.isComprirmir()) {
				String temporal = "temp";
				File directorioTemporal = sa.crearDirectorio(temporal);
				this.comprimirArchivo(archivoSalida,
						directorioTemporal.getAbsolutePath());
				servicioMail
						.addAdjunto(
								sa.obtenerNombreArchivoZipeado(archivoSalida),
								directorioTemporal.getAbsolutePath()
										+ "/"
										+ sa.obtenerNombreArchivoZipeado(archivoSalida));
			} else {
				servicioMail.addAdjunto(archivoSalida.getName(),
						archivoSalida.getAbsolutePath());
			}

			try {
				servicioMail.send();
			} catch (MessagingException e) {
				e.printStackTrace();
			}
		} else {
			throw new NoDestinatariosException();
		}
	}

	private void comprimirArchivo(File file, String directorio) {
		try {
			sa.zippear(file, directorio);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void enviarMailFormatoIncorrecto(ConfiguracionAplicacion conf,
			Resultado resultado) throws NoDestinatariosException {
		MailSender servicioMail = new MailSender(conf);
		servicioMail
				.setAsunto("Resultado ejecucion exitosa pero con error en formato de archivo para - Agregacion de AFIP.  Archivo: "
						+ resultado.getArchivoEntrada());
		List<Contenedor> contenedor = conf.getDestinatariosFalla();
		if (!contenedor.isEmpty()) {
			try {
				servicioMail.setEnviadoPor(conf.getCuentaEnvio());
				for (Contenedor contenedor2 : contenedor) {
					servicioMail.addDestinatario(contenedor2.getNombre());
				}
			} catch (AddressException e) {
				e.printStackTrace();
			}

			servicioMail.setearTexto(resultado);

			try {
				servicioMail.send();
			} catch (MessagingException e) {
				e.printStackTrace();
			}
		} else {
			throw new NoDestinatariosException();
		}
	}

	private void enviarMailDiferenciaTotales(ConfiguracionAplicacion conf,
			Resultado resultado) throws NoDestinatariosException {
		MailSender servicioMail = new MailSender(conf);
		servicioMail
				.setAsunto("Resultado ejecucion con diferencia en controles - Agregacion de AFIP.  Archivo: "
						+ resultado.getArchivoEntrada());
		List<Contenedor> contenedor = conf.getDestinatariosFalla();
		if (!contenedor.isEmpty()) {
			try {
				servicioMail.setEnviadoPor(conf.getCuentaEnvio());
				for (Contenedor contenedor2 : contenedor) {
					servicioMail.addDestinatario(contenedor2.getNombre());
				}
			} catch (AddressException e) {
				e.printStackTrace();
			}

			servicioMail.setearTexto(resultado);

			try {
				servicioMail.send();
			} catch (MessagingException e) {
				e.printStackTrace();
			}
		} else {
			throw new NoDestinatariosException();
		}
	}

}
